![]() |
![]() |
|
Der Code erinnert uns an den Code einer Konsolenanwendung, die als Startpunkt der Laufzeit in einer Klasse Program die statische Methode Main enthält. Genauso ist es auch bei einer Windows-Anwendung. Allerdings wird bereits Programmcode vorgegeben, denn schließlich soll dem Anwender das erste Windows-Fenster der Anwendung angezeigt werden und nicht die Konsole. a
Die Nachrichtenschleife und die Methode »Application.Run«Ein grundlegender Unterschied zwischen einer Konsolen- und einer Windows-Anwendung ist die so genannte Nachrichtenschleife. Als Nachricht ist ein Ereignis zu verstehen. Windows-Programme reagieren auf Ereignisse, und eine Nachrichtenschleife ist sensibilisiert, ununterbrochen auf eingehende Ereignisse zu lauern. Ob es sich um Ereignisse der Maus, der Tastatur oder um Ereignisse von Peripheriegeräten wie beispielsweise den Drucker handelt, spielt keine Rolle. Beim Starten einer Windows-Anwendung wird nicht automatisch eine Nachrichtenschleife erstellt; das muss ausdrücklich im Programmcode erfolgen. Dazu dient die statische Methode Run der Klasse Application.
Als Argument wird Run eine neue Instanz der Klasse Form1 übergeben. Dabei handelt es sich um das Anwendungsfenster, das in den beiden Dateien Form1.cs und Form1.Designer.cs definiert ist. Beim Aufruf von Run passieren mehrere Dinge:
Jeder Start einer Anwendung hat zur Folge, dass ein neuer Prozess eröffnet wird, der einen Thread hat, in dem sich die Vorgänge der Anwendung abspielen (zumindest solange Sie keinen zusätzlichen Thread erstellen). Eine Nachrichtenschleife ist immer an einen bestimmten Thread gebunden. Durch den Aufruf von Run mit Übergabe einer Form1-Instanz wird die Nachrichtenschleife an den Primärthread der Anwendung und darüber hinaus auch an die Form gebunden. Schließen Sie das Form-Objekt, wird auch die Anwendung beendet. Es handelt sich hierbei gewissermaßen um das Hauptfenster der Anwendung. Werden aus dem Hauptfenster heraus weitere Fenster geöffnet und das Hauptfenster anschließend geschlossen, wird auch die Laufzeit der Anwendung beendet. Das hat zur Folge, dass automatisch alle anderen noch geöffneten Fenster gleichzeitig geschlossen werden. Application.Run ist überladen. Sie können auch die parameterlose Variante einsetzen und haben damit erreicht, dass die Lebensdauer der Nachrichtenschleife nicht mehr an die Existenz der Startform gebunden ist.
Jetzt verhält sich die Anwendung ganz anders, denn mit dem Schließen der Form wird die Anwendung nicht beendet. Sie sehen die Form zwar nicht mehr, aber die Nachrichtenschleife lebt weiter und wartet auf Ereignisse, die nicht mehr kommen können. Im ersten Moment scheint dieses Verhalten ein Handicap zu sein, dennoch ist auch die parameterlose Run-Methode von Bedeutung. Wir werden darauf noch zu sprechen kommen, wenn wir uns mit Windows-Anwendungen beschäftigen, die mehrere Fenster haben. Das Windows XP-DarstellungsformatMit dem Erscheinen von Windows XP ist ein neues Layout in Mode gekommen. Ich muss zugeben, mir gefällt es nicht, und ich ziehe das klassische vor, wie Sie auch an den Abbildungen in diesem Buch erkennen können. Nichtsdestotrotz müssen wir auf das Windows XP-Layout, dessen inoffizieller Name »Luna« lautet, berücksichtigen, um den Anwendern die Möglichkeit zu geben, in den Genuss dieser Oberflächen zu kommen. Voraussetzung der Darstellung der Steuerelemente im XP-Layout ist der Aufruf der Methode Application.EnableVisualStyles. Das erledigt das Visual Studio 2005 für uns, bevor Application.Run aufgerufen wird. Im Hintergrund wird dem Programm damit mitgeteilt, die Datei comctrl6.dll zu verwenden, die ab Windows XP verfügbar und für das typische XP-Erscheinungsbild der Steuerelemente zuständig ist. In Abbildung 15.6 sehen Sie das Fenster der obigen Windows-Anwendung in zwei Darstellungsformaten: links das von Windows XP, rechts das klassische.
Abbildung 15.6 Das Windows XP und das klassische Darstellungsformat 15.3.2 Die Dateien »Form1.cs« und »Form1.Designer.cs«
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| partial class Form1 { |
| /// <summary> |
| /// Erforderliche Methode für die Designerunterstützung. |
| /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. |
| /// </summary> |
| private void InitializeComponent() { |
| this.txtOriginal = new System.Windows.Forms.TextBox(); |
| this.txtKopie = new System.Windows.Forms.TextBox(); |
| this.btnKopieren = new System.Windows.Forms.Button(); |
| this.btnBeenden = new System.Windows.Forms.Button(); |
| this.SuspendLayout(); |
| // |
| // txtOriginal |
| // |
| this.txtOriginal.Location = new System.Drawing.Point(13, 13); |
| this.txtOriginal.Name = "txtOriginal"; |
| this.txtOriginal.Size = new System.Drawing.Size(127, 20); |
| this.txtOriginal.TabIndex = 0; |
| // |
| // txtKopie |
| // |
| this.txtKopie.Location = new System.Drawing.Point(13, 51); |
| this.txtKopie.Name = "txtKopie"; |
| this.txtKopie.Size = new System.Drawing.Size(127, 20); |
| this.txtKopie.TabIndex = 1; |
| // |
| // btnKopieren |
| // |
| this.btnKopieren.Location = new System.Drawing.Point(171, 13); |
| this.btnKopieren.Name = "btnKopieren"; |
| this.btnKopieren.Size = new System.Drawing.Size(127, 23); |
| this.btnKopieren.TabIndex = 2; |
| this.btnKopieren.Text = "Kopieren"; |
| this.btnKopieren.Click += new System.EventHandler(this.btnKopieren_Click); |
| ... |
| } |
| private System.Windows.Forms.TextBox txtOriginal; |
| private System.Windows.Forms.TextBox txtKopie; |
| private System.Windows.Forms.Button btnKopieren; |
| private System.Windows.Forms.Button btnBeenden; |
| } |
In erster Linie handelt es sich um die Eigenschaftseinstellungen der beteiligten Komponenten, die von der Standardvorgabe des jeweiligen Typs abweichen, also objektspezifisch sind. Es sind die Einstellungen, die Sie im Eigenschaftsfenster der Komponente vornehmen und aus der Lage und Größe der Komponente im Designer resultieren. Die Entwicklungsumgebung setzt das selbstständig in den dazu passenden Code um.
Beachten Sie auch bitte unbedingt den XML-Kommentar zu InitializeComponent. Aus eigener Erfahrung kann ich Ihnen nahe legen, diesen zu beherzigen und wirklich keine Änderungen am Code in InitializeComponent vornehmen. Ich kann davon berichten, dass ich meine Ignoranz mit dem Verlust sämtlicher Steuerelemente in einer Form bezahlen musste.
Neben der Initialisierungsmethode werden auf Klassenebene auch alle Steuerelemente standardmäßig private deklariert. Die Initialisierung der Objekte erfolgt innerhalb von InitializeComponent.
Kommen wir nun zum Code in der Datei Form1.cs.
| public partial class Form1 : Form { |
| public Form1() { |
| InitializeComponent(); |
| } |
| // Behandelt das Click-Ereignis der Schaltfläche 'Kopieren' |
| private void btnKopieren_Click(object sender, EventArgs e) { |
| txtKopie.Text = txtOriginal.Text; |
| } |
| // Behandelt das Click-Ereignis der Schaltfläche 'Beenden' |
| private void btnBeenden_Click(object sender, EventArgs e) { |
| Application.Exit(); |
| } |
| } |
Wir finden einen parameterlosen Konstruktor, aus dem heraus die weiter oben beschriebene Methode InitializeComponent aufgerufen wird, um die Komponenten zu initialisieren und die Starteigenschaften festzulegen. Neben dem Standardkonstruktor sind in Form1.cs alle benutzerdefinierten Methoden implementiert, zu denen natürlich auch die Ereignishandler zu zählen sind. In unserem Beispiel handelt es sich um die Ereignishandler, die beim Klicken auf die beiden Schaltflächen ausgeführt werden sollen: btnKopieren_Click und btnBeenden_Click.
Der Vorteil partieller Klassen wird jetzt auf zweierlei Weise deutlich:
| Der benutzerdefinierte Code ist von dem Code, den die Entwicklungsumgebung generiert, getrennt. Dadurch wird der Entwickler nicht so schnell der Verlockung nachgeben, eventuell doch Änderungen in InitializeComponent durchzuführen. |
| Der wesentliche Teil des Programmcodes, nämlich der benutzerdefinierte, wird überschaubarer, was insbesondere dem Programmieranfänger den Einstieg erleichtert. |
| << zurück |
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.